/**
 * 
 */
package com.ditty.invoke.action;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.ditty.interceptor.AbstractActionIntercptor;

/**
 * @author dingnate
 *
 */
public class ActionInvoker implements IActionInvoker {
	private Object controller;
	private AbstractActionIntercptor interceptor;
	private Method method;
	private Object[] args;
	private Object returnValue;
	private boolean invoked;

	public ActionInvoker(Action action, Object controller, Object[] args) {
		this.method = action.getMethod();
		this.interceptor = action.getInterceptor();
		this.controller = controller;
		this.args = args;

	}

	@Override
	public ActionInvoker inovke() {
		if (interceptor != null) {
			AbstractActionIntercptor pop = interceptor;
			interceptor = interceptor.next;
			pop.interceptor(this);
		} else if (!invoked) {
			invoked = true;
			try {
				returnValue = method.invoke(controller, args);
			} catch (InvocationTargetException e) {
				Throwable targetException = e.getTargetException();
				throw targetException instanceof RuntimeException ? (RuntimeException) targetException : new RuntimeException(targetException);
			} catch (Throwable e) {
				throw new RuntimeException(e);
			}
		}
		return this;
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T getReturnValue() {
		return (T) returnValue;
	}
}
